
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <errno.h>

#define MAXLEN 1024

// 用于获取用户输入信息的全部变量
char user_input_info[MAXLEN];

// 命令行参数表
int g_argc;
char* g_argv[MAXLEN];

// 环境变量表
char* g_env[MAXLEN];

// 重定向信息
char* g_redirect_info[3]; // g_redirect_info[id] = filename

extern char** environ;

void AccEnvVar()
{
    int i = 0;
    while(environ[i])
    {
        g_env[i] = (char*)malloc(strlen(environ[i]) + 1);
        if(g_env[i] == NULL)
        {
            perror("malloc:");
            break;
        }
        strcpy(g_env[i],environ[i]);
        putenv(g_env[i]); // 1, 模拟从系统配置文件中获得环境变量，导入上下文中，其实这些工作是操作系统帮我们做的
        i++;
    }
    g_env[i] = NULL;
    putenv((char*)"HOSTNAME=涂山苏苏"); // 主机名
    //environ = g_env[]; // 2. 将自己的创建的指针数组，作为环境变量表进行使用，只不过位置是在数据段的。不是在命令行参数环境变量区域。
}
    
void CmdLinePromte()
{
    char* pwd= getenv("PWD");
    int len = strlen(pwd);

    char pwd_cpy[len + 1];
    int i = len - 1;
    for(;i>=0 && pwd[i] != '/';i--);
    if(len != 1) i++;
    strcpy(pwd_cpy,&pwd[i]);

    printf("[%s@%s %s]!",getenv("USER"),getenv("HOSTNAME"),pwd_cpy);
    fflush(stdout); // 刷新缓冲区
}

bool GetUserInputInfo()
{   
    char* ret = fgets(user_input_info,MAXLEN,stdin);
    ret[strlen(ret) -1] = '\0';

    if(ret == NULL && strlen(ret) == 1) return false;
    else return true;
}

void GetRedirectType(char* str,char ch)
{
    int id = -1,char * 
    if(ch == '>')
    {
        // 1.判断是输出重定向  追加重定向 还是错误重定向？
        if((str[-1] == ' ' || str[-1] == '1') && str[1] != '>')
        {
            g_redirect_info[1]
        }
        else if((str[-1] == ' ' || str[-1] == '1') && str[1] == '>')
        {
    
        }
        else if(str[-1] == '2' && str[1] != '>')
        {
    
        }
        else if(str[1] == '2' && str[1] == '>')
        {
    
        }
    }
    else
    {

    }
}

bool RedirAnaly()
{
    int n = strlen(user_input_info) + 1; 
    char str[n];
    strcpy(str,user_input_info);

#define REDIRECT_BREAK "><"
    char* ret = strtok(user_input_info,REDIRECT_BREAK);
    // user_input_info + index = ret
    int pos = ret - user_input_info;
    GetRedirectType(ret,str[pos]);

    
    


    //PublicDectorywhile((g_argv[g_argc++] = strtok(NULL,REDIRECT_BREAK)));

//    char* str = user_input_info;
//
//    for(size_t i = 0;i < strlen(str);i++)
//    {
//    }
}

void CmdLineAnaly(char* string)
{
#define BREAK " "
    g_argc = 0;
    g_argv[g_argc++] = strtok(string,BREAK);
    while((g_argv[g_argc++] = strtok(NULL,BREAK)));
    g_argc--;
}

bool CheckExeBuiltInCmd()
{
    char* cmd = g_argv[0];
    if(strcmp(cmd,"cd") == 0)
    {
        char* path[3] = { 0 };
        path[0] = getenv("HOME");
        path[1] = getenv("PWD");
        path[2] = getenv("OLDPWD");

        if(g_argc == 1) // 只有cd命令：默认用户家目录
        {
            int ret = chdir(path[0]);
            if(ret == -1)
            {
                perror("chdir mistake:");
                return true;
            }
            char cur_pwd[MAXLEN] = "PWD=";
            char* ret_ptr = getcwd(cur_pwd+4,sizeof(cur_pwd) - 1);
            if(ret_ptr == NULL)
            {
                perror("getcwd mistake:");
                return true;
            }


            putenv(cur_pwd);
        }
        return true;
    }
    else if(strcmp(cmd,"echo") == 0)
    {
        return true;
    }
    // else if ... 其它内建命令...
    else 
        return false;
}

int ProcessReplace()
{
    pid_t id = fork();
    if(id == -1) return errno;
    else if(id == 0)
    {
        execvp(g_argv[0],g_argv);
	prinf("出错误");
        return errno; // 替换失败了一定是第一个参数出现了问题
    }
    waitpid(id,NULL,0);
    return 0;
}

int main()
{
    // 0.维护环境变量表
    AccEnvVar();
    while(1)
    {
        // 1.打印命令行
        CmdLinePromte();
        // 2.读取用户输入的信息
        bool ret = GetUserInputInfo(); 
        if(!ret) continue;
        // 3.检查重定向
        RedirAnaly();
        // 4.分析用户输入的信息
        CmdLineAnaly();
        // 5.检擦并执行内建命令
        ret = CheckExeBuiltInCmd();
        if(ret) continue;
        // 6.对非内建命令进行子进程替换
        flag = ProcessReplace();
        if(ret) printf("-涂山苏苏: %s: command not found\n",g_argv[0]);
    }
}

